/**
 * @author YJSYS
 *
 */

package com.qd.extcam;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.StatFs;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class ExtCamActivity extends Activity implements  IOnHandlerMessage/*, ChannelListener, ConnectionInfoListener*/ {
	public static final String TAG = "ExtCamActivity";
	public static String EXTCAM_DIR;
	public static boolean running;
	public boolean mIsStartLog = false;
	public static final long MIN_FREE_MEMORY_SIZE = 100 * 1024 * 1024L;	// MB

	private static final int HANDLER_CHECK_MEMORY_SIZE = 1;
	private static final int TIMEOUT_CHECK_MEMORY_SIZE = 5 * 1000;	// mSec

	private WeakRefHandler mHandler = null;
	private SurfaceView cameraView;
	private ExtRecorder er;

	private SensorManager mSensorManager;
	private long mSensorCount = 0;
	private int mSensorDelay = SensorManager.SENSOR_DELAY_NORMAL;	// SENSOR_DELAY_FASTEST > SENSOR_DELAY_GAME > SENSOR_DELAY_UI > SENSOR_DELAY_NORMAL
	private LogFile mSensorLogFile = null;
	private float mAzimuth;	// 방위각
	private float mPitch;	// 앞/뒤
	private float mRoll;	// 좌/우
	private float[] mAccels;

	// GPS variable
	private LocationManager mLocationManager;
	private long mLocationCount = 0;
	private long mLocationTime = 0;			// milliseconds
	private float mLocationDistance = 0;	// meters
	private LogFile mLocationLogFile = null;
	private double mLatitude;	// 위도	
	private double mLongitude;	// 경도
	private double mAltitude;	// 고도
	private float mSpeed;		// 속도
	private long mUtcTime;		// 시간
	private double mMaxLatitude;
	private double mMinLatitude;
	private double mMaxLongitude;
	private double mMinLongitude;

	private WakeLock mWakeLock = null;
	private SoundPool mSoundPool = null;
	private int mSoundId = 0;
	private long mKeyTime = 0;

	private native int getWidth();
	private native int getHeight();
	private native int getBitsPerPixel();
	private native int getFrameBuffer(byte[] buff);
	static {
		System.loadLibrary("fbuffer");	//TODO
	}

	/** 
	 * @return 현재  mAzimuth 을 리턴한다.
	 */
	public float getAzimuth() {
		return mAzimuth;
	}

	/**
	 * @return 현재  mPitch 을 리턴한다.
	 */
	public float getPitch() {
		return mPitch;
	}

	/**
	 * @return 현재  mRoll 을 리턴한다.
	 */
	public float getRoll() {
		return mRoll;
	}

	public float getAccels(int idx) {
		if (mAccels.length > idx) {
			return mAccels[idx];
		} else {
			return Float.NaN;
		}
	}

	/**
	 * @return 현재  mLatitude 을 리턴한다.
	 */
	public double getLatitude() {
		return mLatitude;
	}

	/**
	 * @return 현재  mLongitude 을 리턴한다.
	 */
	public double getLongitude() {
		return mLongitude;
	}

	/**
	 * @return 현재  mAltitude 을 리턴한다.
	 */
	public double getAltitude() {
		return mAltitude;
	}

	/**
	 * @return 현재  mSpeed 을 리턴한다.
	 */
	public float getSpeed() {
		return mSpeed;
	}

	/**
	 * @return 현재  mUtcTime 을 리턴한다.
	 */
	public long getUtcTime() {
		return mUtcTime;
	}

	public double getMaxLatitude() {
		return mMaxLatitude;
	}

	public double getMinLatitude() {
		return mMinLatitude;
	}

	public double getMaxLongitude() {
		return mMaxLongitude;
	}

	public double getMinLongitude() {
		return mMinLongitude;
	}

	/** 
	 * @return 현재 녹화중인 영상의 프레임 정보를 JPEG 포맷 형태로 린턴한다.
	 */
	public byte[] getJpegFrameBuffer(String tempFile) {
		if (Build.MODEL.equalsIgnoreCase("YJSYS on SMDK4x12")) {
			// get frame buffer
			int WIDTH = getWidth();
			Log.e(TAG, "WIDTH = " + WIDTH);
			int HEIGHT = getHeight();
			Log.e(TAG, "HEIGHT = " + HEIGHT);
			int BYTE_PER_PIXEL = getBitsPerPixel() / 8;
			Log.e(TAG, "BYTE_PER_PIXEL = " + BYTE_PER_PIXEL);

			int SCREEN_NUM = 1;
			int bufSize = WIDTH * HEIGHT * BYTE_PER_PIXEL * SCREEN_NUM;
			byte[] buffer = new byte[bufSize];

			// crate bitmap
			BitmapFactory.Options bfo = new BitmapFactory.Options();
			bfo.inPreferredConfig = Bitmap.Config.ARGB_8888;
			bfo.outWidth = WIDTH;
			bfo.outHeight = HEIGHT;

			if (getFrameBuffer(buffer) == 0) {
				// copy to bitmap
				ByteBuffer byteBuffer = ByteBuffer.allocate(bufSize / SCREEN_NUM);        
				byteBuffer.put(buffer, 0, bufSize / SCREEN_NUM);
				byteBuffer.rewind();

				Bitmap bitmap = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ARGB_8888);
				bitmap.copyPixelsFromBuffer(byteBuffer);
				Bitmap scaled = Bitmap.createScaledBitmap(bitmap, WIDTH/2, HEIGHT/2, false);
				bitmap.recycle();

				ByteArrayOutputStream out = new ByteArrayOutputStream();
				scaled.compress(Bitmap.CompressFormat.JPEG, 80, out);

				return out.toByteArray();
			}
		} else {
			File testFile = new File(EXTCAM_DIR, tempFile);
			try {
				FileInputStream fis = new FileInputStream(testFile);
				ByteArrayOutputStream out = new ByteArrayOutputStream();
				byte[] buff = new byte[256];
				while (fis.read(buff) > 0) {
					out.write(buff);
				}
				fis.close();
				return out.toByteArray();
			} catch (FileNotFoundException e1) {
				e1.printStackTrace();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}

		return null;
	}

	// WifiDirect
	/*private WifiP2pManager manager;
	//private boolean isWifiP2pEnabled = false;
	private boolean retryChannel = false;

	private final IntentFilter intentFilter = new IntentFilter();
	private Channel channel;
	private BroadcastReceiver receiver = null;

	public void setIsWifiP2pEnabled(boolean isWifiP2pEnabled) {
		this.isWifiP2pEnabled = isWifiP2pEnabled;
	}*/

	/* (non-Javadoc)
	 * @see android.app.Activity#onCreate(android.os.Bundle)
	 */
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		ExtCamActivity.EXTCAM_DIR = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "ExtCamData";
		ExtCamActivity.running = true;

		// <uses-permission android:name="android.permission.WRITE_SETTINGS" />
		try {
			int nTimeout = Settings.System.getInt(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT);
			Log.e(TAG, "SCREEN_OFF_TIMEOUT = " + nTimeout);

			nTimeout = -1;
			Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, nTimeout);
		} catch (SettingNotFoundException e) {
			e.printStackTrace();
		}

		mHandler = new WeakRefHandler((IOnHandlerMessage)this);

		mSoundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
		mSoundPool.setOnLoadCompleteListener(mOnLoadCompleteListener);
		mSoundPool.load(this, R.raw.war_gunshot, 1);
		mKeyTime = System.currentTimeMillis();

		if (getIntent().getBooleanExtra("EXTRA_SHUTDOWN", false)) {
			return;
		}

		cameraView = (SurfaceView)findViewById(R.id.smallcameraview);

		//wifidirect
		/*intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
		intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
		intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
		intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);

		manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
		channel = manager.initialize(getApplicationContext(), getMainLooper(), null);

		try {
			Class<?> wifiManager = Class
					.forName("android.net.wifi.p2p.WifiP2pManager");

			Method method = wifiManager
					.getMethod(
							"enableP2p",
							new Class[] { android.net.wifi.p2p.WifiP2pManager.Channel.class });

			method.invoke(manager, channel);

		} catch (Exception e) {
			e.printStackTrace();
		}
		 */
		// Sensor & GPS
		mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
		mLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

		// Sensor & GPS Log File
		mSensorLogFile = new LogFile(this);
		mSensorLogFile.setFileName("log_sensor.txt");
		mLocationLogFile = new LogFile(this);
		mLocationLogFile.setFileName("log_gps.txt");

		registerSensorListener(mSensorDelay);
		mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, mLocationTime, mLocationDistance, mLocationListener);

		Button bt = (Button)findViewById(R.id.start_button);
		bt.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				String fileName = Long.toString(System.currentTimeMillis());
				startRecording(fileName);
			}
		});

		bt = (Button)findViewById(R.id.stop_button);
		bt.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				stopRecording();
			}
		});

		new ServerAsyncTask(this).execute();

		mWakeLock = ((PowerManager)getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.FULL_WAKE_LOCK, "WakeAlways");
		mWakeLock.acquire();	// 항상 화면이 켜지도록 수정
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		switch (keyCode) {
		case KeyEvent.KEYCODE_DPAD_CENTER:
		case KeyEvent.KEYCODE_DPAD_LEFT:
		case KeyEvent.KEYCODE_DPAD_UP:
		case KeyEvent.KEYCODE_DPAD_RIGHT:
		case KeyEvent.KEYCODE_DPAD_DOWN:
		case KeyEvent.KEYCODE_VOLUME_UP:
		case KeyEvent.KEYCODE_VOLUME_DOWN:
		case KeyEvent.KEYCODE_MENU:
			long curKeyTime = System.currentTimeMillis();
			if (mKeyTime > curKeyTime) {
				return super.onKeyDown(keyCode, event);
			}
			mKeyTime = curKeyTime + 3000;

			if (mIsStartLog) {
				mSoundPool.play(mSoundId, 1, 1, 0, 0, 1);
				Log.i(TAG, "onKeyDown() : stopRecording()");
				stopRecording();
			} else {
				mSoundPool.play(mSoundId, 1, 1, 0, 1, 1);
				Log.i(TAG, "onKeyDown() : startRecording()");
				startRecording(null);
			}
			return true;

		default:
			return super.onKeyDown(keyCode, event);
		}
	}
	/* (non-Javadoc)
	 * @see android.app.Activity#onBackPressed()
	 */
	@Override
	public void onBackPressed() {
		finish();

		super.onBackPressed();
	}

	/* (non-Javadoc)
	 * @see android.app.Activity#onDestroy()
	 */
	@Override
	public void onDestroy() {
		mHandler.removeMessages(HANDLER_CHECK_MEMORY_SIZE);
		mWakeLock.release();
		mSoundPool.release();
		ExtCamActivity.running = false;
		mSensorManager.unregisterListener(mSensorListener);
		mLocationManager.removeUpdates(mLocationListener);

		super.onDestroy();
	}

	/* (non-Javadoc)
	 * @see android.app.Activity#onResume()
	 */
	@Override
	public void onResume() {
		super.onResume();
		//receiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
		//registerReceiver(receiver, intentFilter);
	}

	/* (non-Javadoc)
	 * @see android.app.Activity#onPause()
	 */
	@Override
	public void onPause() {
		super.onPause();
		//unregisterReceiver(receiver);
	}

	/**
	 * @param delay
	 */
	private void registerSensorListener(int delay) {
		mSensorManager.unregisterListener(mSensorListener);
		mSensorManager.registerListener(mSensorListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), delay);
		mSensorManager.registerListener(mSensorListener, mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), delay);
		mSensorManager.registerListener(mSensorListener, mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE), delay);
	}

	SensorEventListener mSensorListener = new SensorEventListener() {
		private float[] mMagneticData;
		private float[] mRotation = new float[9];
		private float[] mRotation2 = new float[9];
		private float[] mResult = new float[3];	// azimuth, pitch, roll

		/* (non-Javadoc)
		 * @see android.hardware.SensorEventListener#onAccuracyChanged(android.hardware.Sensor, int)
		 */
		public void onAccuracyChanged(Sensor sensor, int accuracy) {
			Log.d(TAG, "onAccuracyChanged(" + accuracy + ")");
		}

		/* (non-Javadoc)
		 * @see android.hardware.SensorEventListener#onSensorChanged(android.hardware.SensorEvent)
		 */
		public void onSensorChanged(SensorEvent event) {
			switch (event.sensor.getType()) {
			case Sensor.TYPE_ACCELEROMETER:
				mAccels = event.values.clone();
				break;
			case Sensor.TYPE_MAGNETIC_FIELD:
				mMagneticData = event.values.clone();
				return;
			case Sensor.TYPE_GYROSCOPE:
			default:
				return;
			}

			if ((null != mAccels) && (null != mMagneticData)) {
				SensorManager.getRotationMatrix(mRotation, null, mAccels, mMagneticData);
				boolean isRemap = true;
				if (isRemap) {
					SensorManager.remapCoordinateSystem(mRotation, SensorManager.AXIS_Y, SensorManager.AXIS_Z, mRotation2);
					SensorManager.getOrientation(mRotation2, mResult);
				} else {
					SensorManager.getOrientation(mRotation, mResult);
				}

				mAzimuth = (float)Math.toDegrees(mResult[0]);
				if (0 > mAzimuth) {
					mAzimuth += 360;
				}
				if (isRemap) {
					mPitch = (float)Math.toDegrees(mResult[2]);
					mRoll = (float)Math.toDegrees(mResult[1]);
				} else {
					mPitch = (float)Math.toDegrees(mResult[1]);
					mRoll = (float)Math.toDegrees(mResult[2]);
				}

				if (mIsStartLog) {
					String log = mAzimuth + "," + mPitch + "," + mRoll + "," + mAccels[0] + "," + mAccels[1] + "," + mAccels[2];
					mSensorLogFile.write(log);
				}

				mSensorCount++;
				TextView tv = (TextView)findViewById(R.id.msg_1);
				tv.setText(String.format("Sensor(%d) : Azimuth(%f) / Pitch(%f) / Roll(%f) / Accels(%f,%f,%f)",
						mSensorCount, mAzimuth, mPitch, mRoll, mAccels[0], mAccels[1], mAccels[2]));
			}
		}
	};

	LocationListener mLocationListener = new LocationListener() {

		/* (non-Javadoc)
		 * @see android.location.LocationListener#onLocationChanged(android.location.Location)
		 */
		public void onLocationChanged(Location location) {
			double latitude = location.getLatitude();
			double longitude = location.getLongitude();
			double altitude = location.getAltitude();
			float speed = (float)(location.getSpeed() * 3.6);	// m/s -> m/h
			long utcTime = location.getTime();

			if ((mLatitude != latitude) || (mLongitude != longitude) || (mAltitude != altitude)
					|| (mSpeed != speed) || (mUtcTime != utcTime)) {
				mLatitude = latitude;
				mLongitude = longitude;
				mAltitude = altitude;
				mSpeed = speed;
				mUtcTime = utcTime;

				if (mIsStartLog) {
					String log = mLatitude + "," + mLongitude + "," + mAltitude + "," + mSpeed + "," + mUtcTime;
					mLocationLogFile.write(log);

					if (mLatitude > mMaxLatitude) {
						mMaxLatitude = mLatitude;
					}
					if (mLatitude < mMinLatitude) {
						mMinLatitude = mLatitude;
					}

					if (mLongitude > mMaxLongitude) {
						mMaxLongitude = mLongitude;
					}
					if (mLongitude < mMinLongitude) {
						mMinLongitude = mLongitude;
					}
				} else {
					mMaxLongitude = mMaxLatitude = Double.MIN_VALUE;
					mMinLongitude = mMinLatitude = Double.MAX_VALUE;
				}

				mLocationCount++;
				TextView tv = (TextView)findViewById(R.id.msg_2);
				tv.setText(String.format("Location(%d) : Latitude(%f) / Longitude(%f) / mAltitude(%f) / Speed(%f) / UtcTime(%d)",
						mLocationCount, mLatitude, mLongitude, mAltitude, mSpeed, mUtcTime));
			}
		}

		/* (non-Javadoc)
		 * @see android.location.LocationListener#onProviderDisabled(java.lang.String)
		 */
		public void onProviderDisabled(String provider) {
			Log.d(TAG, "onProviderDisabled(" + provider + ")");
		}

		/* (non-Javadoc)
		 * @see android.location.LocationListener#onProviderEnabled(java.lang.String)
		 */
		public void onProviderEnabled(String provider) {
			Log.d(TAG, "onProviderEnabled(" + provider + ")");
		}

		/* (non-Javadoc)
		 * @see android.location.LocationListener#onStatusChanged(java.lang.String, int, android.os.Bundle)
		 */
		public void onStatusChanged(String provider, int status, Bundle extras) {
			Log.d(TAG, "onStatusChanged(" + provider + ", " + status + ")");
		}
	};

	/** 녹화를 시작한다.
	 * @param fileName 녹화 파일명
	 */
	public void startRecording(String aFileName) {
		String fileName = null;
		if (null == aFileName) {
			fileName = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date());
			fileName = "L" + fileName;
		} else {
			fileName = aFileName;
		}
		Log.i(TAG, "startRecording : " + fileName);

		mSensorLogFile.setFileName(fileName + ".sensor");
		mLocationLogFile.setFileName(fileName + ".location");
		if (er == null) {
			er = new ExtRecorder(this, cameraView.getHolder());
			er.setSensorFile(mSensorLogFile.getFileNameWithFullPath());
			er.setLocationFile(this.mLocationLogFile.getFileNameWithFullPath());
			er.InitMediaRecorder(fileName);
			er.prepare();
			er.start();
		}
		long startTime = System.currentTimeMillis();
		mSensorLogFile.setStartTime(startTime);
		mLocationLogFile.setStartTime(startTime);

		mSensorCount = 0;
		mLocationCount = 0;
		mIsStartLog = true;

		mHandler.sendEmptyMessageDelayed(HANDLER_CHECK_MEMORY_SIZE, TIMEOUT_CHECK_MEMORY_SIZE);
	}

	/** 녹화를 중지한다.
	 * 
	 */
	public void stopRecording() {
		if (er != null)
			er.stop();
		er = null;

		mIsStartLog = false;

		mHandler.removeMessages(HANDLER_CHECK_MEMORY_SIZE);
	}

	/** 사운드 리소스 로딩을 감시한다.
	 * 
	 */
	private SoundPool.OnLoadCompleteListener mOnLoadCompleteListener = new SoundPool.OnLoadCompleteListener() {
		/* (non-Javadoc)
		 * @see android.media.SoundPool.OnLoadCompleteListener#onLoadComplete(android.media.SoundPool, int, int)
		 */
		@Override
		public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
			mSoundId = sampleId;
			soundPool.play(sampleId, 1, 1, 0, 0, 1);
		}
	};

	@Override
	public void handleMessage(Message msg) {
		switch (msg.what) {
		case HANDLER_CHECK_MEMORY_SIZE:
			long freeSize = getAvailableExternalMemorySize();
			Log.e(TAG, "getAvailableExternalMemorySize() = " + freeSize + ", " + MIN_FREE_MEMORY_SIZE);
			if (MIN_FREE_MEMORY_SIZE > freeSize) {
				stopRecording();
			} else {
				mHandler.sendEmptyMessageDelayed(HANDLER_CHECK_MEMORY_SIZE, TIMEOUT_CHECK_MEMORY_SIZE);
			}
			break;
		}
	}

	public long getAvailableExternalMemorySize() {
		File path = Environment.getExternalStorageDirectory();
		StatFs stat = new StatFs(path.getPath());
		long blockSize = stat.getBlockSize();
		long availableBlocks = stat.getAvailableBlocks();

		return (availableBlocks * blockSize);
	}


	/*
	@Override
	public void onChannelDisconnected() {
		// we will try once more
		if (manager != null && !retryChannel) {
			Toast.makeText(this, "Channel lost. Trying again", Toast.LENGTH_LONG).show();
			retryChannel = true;
			manager.initialize(this, getMainLooper(), this);
		} else {
			Toast.makeText(this,
					"Severe! Channel is probably lost premanently. Try Disable/Re-Enable P2P.",
					Toast.LENGTH_LONG).show();
		}
	}

	@Override
	public void onConnectionInfoAvailable(WifiP2pInfo info) {
		// ������������������

		if (info.groupFormed && info.isGroupOwner) {
			Toast.makeText(this, "Server Init", Toast.LENGTH_LONG).show();
			new ServerAsyncTask(this.context, this).execute();
		} 
	}
	 */
}

class LogFile {
	private String m_strLogFileFolderPath = "";
	private String m_strLogFileName = "filelog.txt";
	private long m_startTime = 0;

	/** 센서, 위치정보를 저장하기 위한 로그파일의 생성자
	 * @param context 메인 Activity의  Context
	 */
	public LogFile(Context context) {
		if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
			m_strLogFileFolderPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "ExtCamData";
		}
		else {
			m_strLogFileFolderPath = File.separator;
		}

		File path = new File(m_strLogFileFolderPath);
		if (false == path.isDirectory()) {
			path.mkdirs();
		}
	}

	/** 로그파일의 파일명을 지정한다.
	 * @param strFileName 로그파일 파일명
	 */
	public void setFileName(String strFileName) {
		if ((null != strFileName) && (0 < strFileName.length())) {
			m_strLogFileName = strFileName;
		}
	}

	/** 
	 * @return 로그파일의 파일명을 Full Path를 포함하여 리턴한다.
	 */
	public String getFileNameWithFullPath() {
		return m_strLogFileFolderPath + File.separator + m_strLogFileName;
	}

	/** 로그파일의 시작시간을 지정한다.
	 * @param startTime
	 */
	public void setStartTime(long startTime) {
		m_startTime = startTime;
	}

	/**
	 *  로그파일을 리셋한다.
	 */
	public void reset() {
		File file = new File(m_strLogFileFolderPath + File.separator + m_strLogFileName);
		file.delete();
	}

	/** 로그파일에 정보를 기록한다.
	 * @param strMessage 정보
	 * @param args 
	 */
	public void write(String strMessage, Object ... args) {
		String _strMessage = strMessage;
		if ((strMessage == null) || (strMessage.length() == 0)) {
			return;
		}

		if (args.length != 0) {
			_strMessage = String.format(strMessage, args);
		}

		_strMessage = (System.currentTimeMillis() - m_startTime) + ":" + _strMessage + "\n";

		File file = new File(m_strLogFileFolderPath + File.separator + m_strLogFileName);
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(file, true);
			if (fos != null) {
				fos.write(_strMessage.getBytes());
			}
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (fos != null) {
					fos.close();
				}
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
}
